home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
001a
/
filesnip.zip
/
FILESNIP.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-07-14
|
43KB
|
1,476 lines
page 60,132
MASM
; This is a modification of the programme described below (SNIPPER).
; 0.0.1 gets all chars on lines between point 1 and point 2
; 0.0.2 allows the use of HOME and END keys to move around the screen.
; 0.0.3 allows hitting ESC key in filename prompt for entering
; completely new file name.
; 0.0.4 fixed bug in ESC key during filename entry. If esc hit and
; then return, will exit without saving to file. if ESC hit
; then chars entered for new filename, will print to file.
; 0.0.5 added new option when writing to file. Entering F will now
; strip out all multiple spaces and any pipes, as well as will
; put 2 spaces after any punctuation. Old write to file
; (unformatted) is now option "U"
; 0.0.6 fixed problem with help box not displaying all options and
; correctly formatting the box.
; 0.0.7 fixed help box display so that it is uses it's own character
; attributes, and restores original attribute upon exit.
; 0.0.8 Added colour to Help Box. Unsure if will work with mono
; 0.0.9 gets filename from first 8 chars or from first char to period,
; of first line of highlight, + .RTT. Refuses all chars which
; filenames can not contain.
; 0.1.0 checks for mono display adapter. if present, displays mono
; help.
; 0.1.1 Modified display of copyright notice.
; 0.1.2 Added use of INS key when moving to top_left position. Hitting
; INS will move the cursor to the 34th column, which is the
; standard starting space for file descriptions on PCB/ProDoor BBSs
; 0.1.3 Fixed problem with getting filename, and hitting ESC. Now
; resets filechar flag so that if used again after hitting esc,
; or entering a new filename, will now find new filename.
; Also, fills out full space for filename with 0H after each
; filename. Previously, if the new filename was shorter than
; the last one entered, there would be residual chars.
; 0.1.4 Fixed problem with underscore as part of a filename. Had
; accidently included it in the list of chars not acceptable.
; 0.1.5 Fixed highlighting problem associated with reading filenames
; of 8 chars + ext.
; 0.1.6 Program sends "fl filename.ext" to keyboard buffer, for file
; flagging on BBS.
; 0.1.7 Pruned program of unused or unnecessary functions relating to
; SNIPPER
; 0.1.8 Extended total filename size to a maximum of 50 chars for
; large paths.
; 0.1.9 Fixed problem with using the program multiple
; times. Wouldn't write more than one file nor would it spit
; out more then "F" on the second use in the file flag section.
; 0.2.0 Reduced Maximum filename length to 12 places in anticipation of
; the use of a path statement on the command line to be added in
; an upcomming version.
; 0.2.1 Added use of pathname on command line. Path statement will
; now be /P=path. Command line must be eithe filesnip by itself
; or filesnip rows,cols,/P=path
; 0.3.0 No modifications - Found no bugs
; 0.4.0 No modifications - Found no bugs
; 0.5.0 No modifications - Found no bugs
; 0.6.0 No modifications - Found no bugs
; 0.7.0 No modifications - Found no bugs
; 0.8.0 No modifications - Found no bugs
; 0.9.0 No modifications - Found no bugs
; 1.0.0 Initial Release - 6 June 1990
; 1.0.1 Made use of path statement flag on command line non-case
; sensitive.
; 1.0.2 Added ESC before flagging of file to download in case user is
; in scrollback mode.
; 1.1.0 Added reformatting of captured text to make it look better in
; the .RTT file. Now, no line will be longer than 72 chars,
; with text broken at spaces.
; 1.1.1 Added breaking of lines at all appropriate places, ie: hyphens,
; slashes, underscores, plus and equal symbols. Also fixed bug
; which occured if for some unknown reason a captured line had
; more than 72 chars in a row (ie. no white spaces)
; 1.2.0 Removed Printer feature as it was more or less useless.
; 1.2.1 Got rid of extra carriage return that was placed in .RTT file
; at end of text. Was causing problems with program used to
; incorporate files into BBS system.
; SNIPPER is a resident utility which allows cutting out a portion
; of the screen. The selected portion may be printed, written
; to disk or entered in the keyboard buffer. Activate SNIPPER by
; pressing CTL-~, then position the cursor in the upper left corner of
; the window using the arrow keys. Press CR to fix the first corner,
; then expand the window with arrow keys. Finally, type "P" to print,
; "F" for disk file, "G" to retrieve or CR for a help menu. Press ESC
; any time to exit SNIPPER. When installing SNIPPER, use the optional
; parameters to expand it's internal buffer for displays (such as the
; EGA) containing more than the standard 25 rows and 80 columns.
; SNIPPER [rows,columns]
;------------------------------------;
; BIOS_SEG IS THE ROM-BIOS DATA AREA ;
;------------------------------------;
BIOS_SEG SEGMENT AT 0040H
ORG 004AH
CRT_COLS DB ? ;CURRENT NUMBER OF COLUMNS
ORG 0050H
CURSOR_POSN DW 8 DUP(?) ;CURRENT CURSOR LOCATION
ORG 0062H
ACTIVE_PAGE DB ? ;ACTIVE PAGE FOR CGA AND EGA
ORG 0084H
ROWS DB ? ;LAST ROW NUMBER FOR EGA
BIOS_SEG ENDS
CSEG SEGMENT
ASSUME CS:CSEG,DS:NOTHING
ORG 0100H ;BEGINNING FOR .COM PROGRAMS
START:
JMP INITIALIZE ;INITIALIZATION CODE IS AT END
;--------------------------------;
; DATA AREA USED BY THIS PROGRAM ;
;--------------------------------;
HOTKEY EQU 29H ;SCAN CODE FOR "~" KEY
SHIFT_MASK EQU 00000100B ;MASK FOR CTL KEY
COPYRIGHT DB 17 DUP(20H),214,44 DUP(196),183
DB 13,10,17 DUP(20H),186,44 DUP(20H),186
DB 10,13,17 DUP(20H),186," File-SNIP 1.2.1 (c) 1990 Mad Monk Software ",186
DB 10,13,17 DUP(20H),186,44 DUP(20H),186
DB 10,13,17 DUP(20H),186,44 DUP(20H),186
DB 10,13,17 DUP(20H),186,7,14 DUP(20H),"Hotkey is CTL-~",7,15 DUP(20H),186
DB 10,13,17 DUP(20H),186,44 DUP(20H),186
DB 10,13,17 DUP(20H),211,44 DUP(196),189,13,10,"$",1AH
PROGRAMMER DB "File-SNIP: Scott Penrose. SNIPPER: Tom Kihlken"
INSTALLED_MSG DB "Already Installed",13,10,"$"
BAD_DOS_MSG DB "Requires DOS 2.0+",13,10,"$"
OLDINT09 DD ? ;OLD KEYBOARD BREAK INTERRUPT VECTOR
OLDINT13 DD ? ;OLD BIOS DISK IO INTERRUPT VECTOR
OLDINT16 DD ? ;OLD KEYBOARD INTERRUPT VECTOR
OLDINT21 DD ? ;OLD DOS FUNCTION INTERRUPT VECTOR
ERR_STAT DB ? ;ERROR STATUS DURING FILE OUTPUT
PATH_N_FILE DB 128 DUP (0)
FILE_PATH DB 114 DUP (0)
FILE_PROMPT DB "Enter Filename: "
FILENAME DB "FILESNIP.RTT" ;THE DEFAULT FILENAME
DB 2 DUP (0) ;LEAVE ROOM FOR DRIVE AND PATH
TEMP_BUFF_START EQU OFFSET INITIALIZE
TEMP_BUFF_NEXT DW TEMP_BUFF_START ;POINTER TO NEXT KEY IN BUFFER
TEMP_BUFF_LAST DW TEMP_BUFF_START ;POINTER TO LAST KEY IN BUFFER
TEMP_BUFF_SIZE EQU 25*(80+2) ;ROOM FOR 25 ROWS OF 80 COLUMNS
TEMP_BUFF_END DW TEMP_BUFF_START+TEMP_BUFF_SIZE
BUFF_START EQU OFFSET INITIALIZE+TEMP_BUFF_SIZE
BUFF_NEXT DW BUFF_START ;POINTER TO NEXT KEY IN BUFFER
BUFF_LAST DW BUFF_START ;POINTER TO LAST KEY IN BUFFER
BUFF_SIZE EQU 25*(80+2) ;ROOM FOR 25 ROWS OF 80 COLUMNS
BUFF_END DW BUFF_START+BUFF_SIZE
FILE_BUFF_START EQU OFFSET INITIALIZE+TEMP_BUFF_SIZE+BUFF_SIZE
FILE_BUFF_NEXT DW FILE_BUFF_START ;POINTER TO NEXT KEY IN BUFFER
FILE_BUFF_LAST DW FILE_BUFF_START ;POINTER TO LAST KEY IN BUFFER
FILE_BUFF_SIZE EQU 13H ;19 bytes
FILE_BUFF_END DW FILE_BUFF_START+FILE_BUFF_SIZE
TOP_LEFT LABEL WORD ;FIRST CORNER OF WINDOW
LEFT_SIDE DB 0 ;COLUMN NUMBER OF LEFT SIDE
TOP_ROW DB 0 ;ROW NUMBER OF TOP SIDE
BOT_RIGHT LABEL WORD ;SECOND CORNER OF WINDOW
RIGHT_SIDE DB ? ;COLUMN NUMBER OR RIGHT SIDE
BOT_ROW DB ? ;ROW NUMBER OF BOTTOM
SEND_CHAR DW ? ;POINTER TO CHARACTER HANDLER
FILE_SEND_CHAR DW ? ;POINTER TO CHARACTER HANDLER
HOME_END_HIT LABEL WORD ;if=1 then home was hit
HOME_END_LOOP DB 0 ;IF=1, then first time in loop
SEND_KEYS DB 0 ;IF=1, USE KEYSTROKES FROM BUFFER
FILE_SEND_KEYS DB 0 ;IF=1, USE KEYSTROKES FROM BUFFER
WRIT_FILE DB 0 ;IF=1, NEED TO WRITE TO DISK
BUSY_FLAGS DB 0 ;BIT MASKED AS FOLLOWS:
; 1 - DOS IS ACTIVE
; 2 - BIOS IO IS ACTIVE
; 4 - SNIPPER IS ACTIVE
DOS_STAT DB 0 ;CURRENT DOS FUNCTION
SPACE_FLAG DB 0 ;Determine if space should be printed
FILECHAR DB 0 ;
FILE_EXT DB 0
CHARS_ON_STACK DB 0 ;How many chars have been printed
PUNCT_FLAG DB 0 ;was any punctuation found?
NO_SPACE_FLAG DB 0
FIRST_CHAR_MARKER DW 0
HELP_MENU DB 201,21 DUP(205),187
DB 186," F - File Formatted ",186
DB 186," Esc- Quit ",186
DB 200,21 DUP(205),188
HELP_MENU_ATTR1 DB 23 DUP(4EH) ;ANSI menu
DB 23 DUP(4EH)
DB 23 DUP(4EH)
DB 23 DUP(4EH)
HELP_MENU_ATTR2 DB 23 DUP(07H) ;ASCII menu
DB 23 DUP(07H)
DB 23 DUP(07H)
DB 23 DUP(07H)
;------------------------------------------------------------------;
; SNIPPER BUILDS THE WINDOW AND ACCEPTS COMMANDS FROM THE KEYBOARD ;
;------------------------------------------------------------------;
SNIPPER PROC NEAR
ASSUME DS:CSEG, ES:BIOS_SEG
XOR BX,BX ;BX IS INCREMENT FOR ROW/COLUMN
GET_KB_KEY1:
MOV DX,TOP_LEFT ;GET LOCATION OF FIRST CORNER
ADD DH,BH ;ADD IN THE ROW INCREMENT
ADD DL,BL ;ADD IN THE COLUMN INCREMENT
CMP DL,0 ;AT LEFT EDGE OF SCREEN?
JGE NOT_LEFT_EDGE
MOV DL,CRT_COLS ;JUMP TO THE RIGHT EDGE
DEC DL
NOT_LEFT_EDGE:
CMP DL,CRT_COLS ;AT RIGHT EDGE OF SCREEN YET?
JB NOT_RIGHT_EDGE ;IF NOT, KEEP MOVING RIGHT
XOR DL,DL ;IF YES, WRAP TO LEFT EDGE
NOT_RIGHT_EDGE:
CMP DH,0 ;AT TOP OF SCREEN YET?
JGE NOT_AT_TOP
MOV DH,ROWS ;JUMP DOWN TO THE BOTTOM
NOT_AT_TOP:
CMP DH,ROWS ;AT BOTTOM OF SCREEN?
JLE NOT_AT_BOTTOM
XOR DH,DH ;JUMP BACK TO THE TOP
NOT_AT_BOTTOM:
MOV TOP_LEFT,DX ;SAVE NEW CORNER LOCATION
CALL REV_VIDEO ;CHANGE IT TO REVERSE VIDEO
XOR AH,AH ;BIOS KEYBOARD INPUT
INT 16H ;GET A KEYSTROKE
PUSH AX
CALL REV_VIDEO ;PUT ATTRIBUTE BACK TO NORMAL
POP AX
CMP AH,1 ;IS IT ESCAPE?
JNE NOT_ESC
RET ;JUST RETURN TO EXIT
NOT_ESC:
MOV BX,0FF00H ;INCREMENT TO SUBTRACT ONE ROW
CMP AH,48H ;IS IT UP ARROW?
JE GET_KB_KEY1
MOV BX,0100H ;INCREMENT TO ADD ONE ROW
CMP AH,50H ;IS IT DOWN ARROW?
JE GET_KB_KEY1
MOV BX,0001H ;INCREMENT TO ADD ONE COLUMN
CMP AH,4FH ;IS IT END KEY?
JE END_HIT ;jump to END_hit
MOV BX,0001H ;INCREMENT TO ADD ONE COLUMN
CMP AH,52H ;IS IT INS KEY?
JE INS_HIT ;jump to PLUS_hit
MOV BX,0001H ;INCREMENT TO ADD ONE COLUMN
CMP AH,4DH ;IS IT RIGHT ARROW?
JE GET_KB_KEY1
MOV BX,00FFH ;INCREMENT TO SUBTRACT ONE COLUMN
CMP AH,47H ;Is it home key
JE HOME_HIT ;jump to home_hit
MOV BX,00FFH ;INCREMENT TO SUBTRACT ONE COLUMN
CMP AH,4BH ;IS IT LEFT ARROW?
JNE NOT_LEFT_ARROW
JMP GET_KB_KEY1
NOT_LEFT_ARROW:
XOR BX,BX
CMP AL,13 ;IS IT A CARRIAGE RETURN?
JNE NOT_CR
MOV DX,TOP_LEFT ;A CARRIAGE RETURN WAS PRESSED
MOV BOT_RIGHT,DX ;INITIALIZE THE SECOND CORNER
CALL REV_VIDEO ;CHANGE IT BACK TO REVERSE VIDEO
JMP SHORT GET_KB_KEY2
NOT_CR:
JMP GET_KB_KEY1 ;JUST GET ANOTHER KEY
HOME_HIT:
MOV DL,0 ;put cursor at beginning of line
MOV BL,0 ;
PUSH DX
MOV DX,TOP_LEFT
MOV DL,0H
MOV TOP_LEFT,DX
POP DX
JMP GET_KB_KEY1 ;JUST GET ANOTHER KEY
END_HIT:
MOV BL,0H ;put cursor at end of line.
MOV DL,0H ;
PUSH DX
MOV DX,TOP_LEFT
MOV DL,4FH
MOV TOP_LEFT,DX
POP DX
JMP GET_KB_KEY1 ;JUST GET ANOTHER KEY
INS_HIT:
MOV BL,0H ;put cursor at 34th column
MOV DL,0H ;
PUSH DX
MOV DX,TOP_LEFT
MOV DL,21H
MOV TOP_LEFT,DX
POP DX
JMP GET_KB_KEY1 ;JUST GET ANOTHER KEY
GET_KB_KEY2:
MOV HOME_END_HIT,0000H ;clear flag for home/end key
XOR AH,AH
INT 16H ;GET A KEYSTROKE
GOT_KEY2: MOV DX,BOT_RIGHT
CMP AH,48H ;IS IT UP ARROW?
JNE NEXT_1
JMP SUB_ROW_1 ;SUBTRACT A ROW FROM WINDOW
NEXT_1:
CMP AH,50H ;IS IT DOWN ARROW?
JNE NEXT_2
JMP ADD_ROW_1 ;ADD A ROW TO THE WINDOW
NEXT_2:
CMP AH,4DH ;IS IT RIGHT ARROW?
JNE NEXT_3
JMP ADD_COL ;ADD A COLUMN TO THE WINDOW
NEXT_3:
CMP AH,4BH ;IS IT LEFT ARROW?
JNE NEXT_4
JMP SUB_COL ;SUBTRACT A COLUMN FROM WINDOW
NEXT_4:
CMP AH,47H ;is it home key.
JNE NEXT_5
MOV HOME_END_HIT,0001H
MOV HOME_END_LOOP,01H
JMP SUB_COL
NEXT_5:
CMP AH,4FH ;is it end key?
JNE NEXT_6
MOV HOME_END_HIT,0100H
JMP ADD_COL
NEXT_6:
JMP NOT_ARROW_KEY
SUB_COL:
CMP DH,TOP_ROW
JG OK_GO_BACK
CMP DL,LEFT_SIDE ;DONT ERASE IT COMPLETELY
JLE GET_KB_KEY2
OK_GO_BACK:
CMP DL,0 ;DONT ERASE IT COMPLETELY
JLE GET_KB_KEY2
DEC DL ;SUBTRACT A COLUMN
MOV RIGHT_SIDE,DL ;SAVE NEW RIGHT SIDE COLUMN
INC DL
DONT_INC_DL:
JMP SHORT COL_LOOP
ADD_COL:
INC DL ;ADD A COLUMN
CMP DL,CRT_COLS ;AT RIGHT EDGE OF SCREEN?
JL ADD_COL_1
JMP GET_KB_KEY2 ;STOP WHEN SCREEN IS FILLED
ADD_COL_1:
MOV RIGHT_SIDE,DL ;SAVE NEW RIGHT SIDE COLUMN
COL_LOOP:
CMP HOME_END_HIT,0001H
JZ COL_LOOP_1
CMP HOME_END_HIT,0100H
JZ COL_LOOP_2
CALL REV_VIDEO ;REVERSE THIS CHARACTER
JMP GET_KB_KEY2
COL_LOOP_1:
CALL REV_VIDEO ;REVERSE THIS CHARACTER
DEC DL
JMP SUB_COL
COL_LOOP_2:
CALL REV_VIDEO ;REVERSE THIS CHARACTER
JMP ADD_COL
SUB_ROW_1:
CMP DH,TOP_ROW ;AT TOP OF WINDOW?
JG SUB_ROW_2
JMP GET_KB_KEY2 ;DONT ERASE IT COMPLETELY
SUB_ROW_2:
PUSH DX
SUB_ROW:
CALL REV_VIDEO
DEC DL ;SUBTRACT A COLUMN
CMP DL,0 ;DONT ERASE IT COMPLETELY
JL SUB_ROW_PLUS
JMP SUB_ROW
SUB_ROW_PLUS:
POP DX
PUSH CX
MOV CX,TOP_LEFT
INC CH
CMP CH,DH
JE ON_SECOND_ROW
JMP SUB_ROW_PLUS_1
ON_SECOND_ROW:
CMP CL,DL
JLE SUB_ROW_PLUS_1
MOV DL,CL
MOV BOT_RIGHT,DX
SUB_ROW_PLUS_1:
POP CX
DEC DH
MOV BOT_ROW,DH
PUSH DX
SUB_ROW_PLUS_2:
CMP DL,79
JGE AT_END
INC DL
CALL REV_VIDEO
JMP SUB_ROW_PLUS_2
AT_END:
POP DX
JMP GET_KB_KEY2
ADD_ROW_1:
CMP DH,ROWS ;AT BOTTOM OF SCREEN?
JL ADD_ROW_1_1
JMP GET_KB_KEY2 ;STOP WHEN SCREEN IS FILLED
ADD_ROW_1_1:
PUSH DX
ADD_ROW:
CMP DL,79
JZ SKIP_INC
INC DL
CALL REV_VIDEO
SKIP_INC:
CMP DL,78
JG ADD_ROW_PLUS
JMP ADD_ROW
ADD_ROW_PLUS:
POP DX
CMP DH,ROWS ;AT BOTTOM OF SCREEN?
JL NOT_BOT
JMP GET_KB_KEY2 ;STOP WHEN SCREEN IS FILLED
NOT_BOT:
INC DH
MOV BOT_ROW,DH
ROW_LOOP:
CALL REV_VIDEO ;REVERSE THIS CHARACTER
DEC DL ;MOVE TO NEXT COLUMN
CMP DL,0 ;AT LEFT EDGE YET?
JGE ROW_LOOP ;CONTINUE UNTIL AT LEFT EDGE
JMP GET_KB_KEY2
NOT_ARROW_KEY:
MOV TEMP_BUFF_NEXT,TEMP_BUFF_START
MOV TEMP_BUFF_LAST,TEMP_BUFF_START
MOV FILE_BUFF_NEXT,FILE_BUFF_START
MOV FILE_BUFF_LAST,FILE_BUFF_START
MOV SEND_CHAR,OFFSET BUFF_CHAR
CMP AH,21H ;IS IT THE "F" KEY
JNE NOT_F
MOV WRIT_FILE,0
MOV FILE_SEND_CHAR,OFFSET FILE_BUFF_CHAR
CALL GET_FILENAME
CMP WRIT_FILE,-1 ;WAS ESCAPE REQUESTED?
JE ERASE_BOX
CALL FORMAT_OUTPUT
CALL COPY_TO_REG_BUFF
MOV WRIT_FILE,1
MOV FILE_SEND_KEYS,01H
TEST BUSY_FLAGS,00000011B ;IS INT21 OR INT13 BUSY?
JNZ RETURN ;IF YES, WAIT TILL LATER
CALL WRITE_TO_FILE ;IF NOT, DO IT NOW
RETURN:
RET
NOT_F:
CMP AH,1 ;IS IT ESCAPE?
JE ERASE_BOX ;IF YES, ERASE BOX AND EXIT
CMP AL,13 ;IS IT A CARRIAGE RETURN?
JE DISPLAY_HELP ;IF YES, DISPLAY HELP
JMP GET_KB_KEY2 ;OTHERWISE JUST GET ANOTHER KEY
ERASE_BOX:
MOV SEND_CHAR,OFFSET RETURN
JMP FORMAT_OUTPUT
DISPLAY_HELP:
CALL EXCHANGE_HELP ;PUT UP THE HELP MENU
XOR AH,AH
INT 16H ;GET ANOTHER KEYSTROKE
PUSH AX ;SAVE THE KEYSTROKE
CALL EXCHANGE_HELP ;PULL DOWN THE HELP MENU
POP AX ;GET BACK THE KEYSTROKE
JMP GOT_KEY2
;*********************************************************************
REV_VIDEO:
CALL READ_CHAR ;READ CHARACTER AND ATTRIBUTE
MOV BL,AH ;SAVE ATTRIBUTE IN BL
AND BL,10001000B ;GET BLINK AND INTENSITY BITS
AND AH,01110111B ;NOW LOOK ONLY AT COLOR BITS
MOV CL,4 ;ROTATE FOUR COUNTS
ROR AH,CL ;ROTATE FOREGROUND AND BACKGROUND
OR BL,AH ;PUT BACK BLINK AND INTENSITY BITS
CALL DISPLAY_CHAR ;WRITE CHARACTER AND ATTRIBUTE
RET
;*********************************************************************
;---------------------------------------------------------------------;
; Proceedure to read char off screen, and send to file formatted.
; 11-05-90 12:15am
;---------------------------------------------------------------------;
FORMAT_OUTPUT:
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV DX,TOP_LEFT ;GET LOCATION OF FIRST CORNER
MOV SPACE_FLAG,00H
MOV PUNCT_FLAG,00H
MOV CHARS_ON_STACK,00H
READ_LOOP_NEW:
CALL REV_VIDEO
CALL READ_CHAR
CMP AL,20H
JNE READ_LOOP_NEW_1
JMP WAS_SPACE
READ_LOOP_NEW_1:
CMP AL,7CH
JNE NOT_PIPE
JMP MOVE_TO_NEXT_CHAR
NOT_PIPE:
CMP AL,21H ;is it a "!"
JNE NOT_PIPE_1
JMP PUNCT
NOT_PIPE_1:
CMP AL,2EH ;is it a "."
JNE NOT_PERIOD
JMP PUNCT
NOT_PERIOD:
CMP AL,3FH ;is it a "?"
JNE NOT_QUESTION
JMP PUNCT
NOT_QUESTION:
CMP AL,3AH ;is it a ":"
JNE NOT_COLON
JMP PUNCT
NOT_COLON:
CMP AL,3BH ;is it a ";"
JNE NOT_SEMICOLON
JMP PUNCT
NOT_SEMICOLON:
READ_NEW_1:
CMP SPACE_FLAG,01
JE SPACE_SET
CALL SEND_CHAR
INC CHARS_ON_STACK
MOVE_TO_NEXT_CHAR:
CMP DH,BOT_ROW
JE LAST_LINE_NEW
INC DL
CMP DL,79
JG MOVE_1
JMP READ_LOOP_NEW
MOVE_1:
PUSH AX
MOV AL,20H
CALL SEND_CHAR
POP AX
MOV CHARS_ON_STACK,00H
MOV SPACE_FLAG,00H
MOV PUNCT_FLAG,00H
INC DH
MOV DL,0
CMP DH,BOT_ROW
JG MOVE_3
JMP READ_LOOP_NEW
MOVE_3:
CALL REV_VIDEO
LAST_LINE_NEW:
INC DL
CMP DL,RIGHT_SIDE
JG LAST_LINE_NEW_1
JMP READ_LOOP_NEW
LAST_LINE_NEW_1:
CALL CR_LF
POP DX
POP CX
POP BX
POP AX
RET
SPACE_SET:
CMP CHARS_ON_STACK,0
JE NO_PUNCT_FLAG
PUSH AX
MOV AX,0020H
CALL SEND_CHAR
POP AX
INC CHARS_ON_STACK
CMP PUNCT_FLAG,01H
JNE NO_PUNCT_FLAG
MOV PUNCT_FLAG,00H
PUSH AX
MOV AX,0020H
CALL SEND_CHAR
POP AX
INC CHARS_ON_STACK
CALL SEND_CHAR
INC CHARS_ON_STACK
MOV SPACE_FLAG,00H
JMP MOVE_TO_NEXT_CHAR
NO_PUNCT_FLAG:
CALL SEND_CHAR
INC CHARS_ON_STACK
MOV SPACE_FLAG,00H
JMP MOVE_TO_NEXT_CHAR
PUNCT:
CMP CHARS_ON_STACK,0
JNE PUNCT_1
JMP READ_NEW_1
PUNCT_1:
MOV PUNCT_FLAG,01H
JMP READ_NEW_1
WAS_SPACE:
MOV SPACE_FLAG,01H
JMP MOVE_TO_NEXT_CHAR
;*********************************************************************
COPY_TO_REG_BUFF:
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV AX,TEMP_BUFF_START
MOV DX,TEMP_BUFF_START
MOV CX,BUFF_START
BUFFER_EXCHANGE_LOOP:
MOV BX,0048H
PUSH DX
INC DX
MOV FIRST_CHAR_MARKER,DX
DEC DX
ADD DX,BX
MOV BX,DX
POP DX
CMP BX,TEMP_BUFF_LAST
JLE BUFF_CHECKING_LOOP
JMP BUFF_EXCHNG_END
BUFF_CHECKING_LOOP:
PUSH AX
MOV AX,[BX]
CMP AL,20H
JE FOUND_SPACE_BEFORE_72_1
CMP AL,5CH
JE FOUND_SPACE_BEFORE_72_1
CMP AL,2FH
JE FOUND_SPACE_BEFORE_72_1
CMP AL,5FH
JE FOUND_SPACE_BEFORE_72_1
CMP AL,2BH
JE FOUND_SPACE_BEFORE_72_1
CMP AL,2DH
JE FOUND_SPACE_BEFORE_72_1
CMP BX,FIRST_CHAR_MARKER
JLE NO_SPACE_IN_LINE
POP AX
DEC BX
JMP BUFF_CHECKING_LOOP
NO_SPACE_IN_LINE:
PUSH DX
MOV DX,BX
ADD DX,47H
MOV BX,DX
POP DX
MOV NO_SPACE_FLAG,01H
FOUND_SPACE_BEFORE_72_1:
POP AX
FOUND_SPACE_BEFORE_72:
CMP AX,BX
JG FINISHED_WITH_LINE
PUSH BX
PUSH DX
MOV BX,AX
MOV DX,[BX]
MOV BX,CX
MOV [BX],DX
POP DX
POP BX
INC CX
INC AX
JMP FOUND_SPACE_BEFORE_72
FINISHED_WITH_LINE:
CMP NO_SPACE_FLAG,01H
JNE NO_HYPHEN_NEEDED
MOV NO_SPACE_FLAG,00H
PUSH BX
PUSH DX
MOV DX,2DH
MOV BX,CX
MOV [BX],DX
POP DX
POP BX
INC CX
NO_HYPHEN_NEEDED:
PUSH BX
PUSH DX
MOV DX,0DH
MOV BX,CX
MOV [BX],DX
POP DX
POP BX
INC CX
PUSH BX
PUSH DX
MOV DX,0AH
MOV BX,CX
MOV [BX],DX
POP DX
POP BX
INC CX
MOV DX,AX
JMP BUFFER_EXCHANGE_LOOP
BUFF_EXCHNG_END:
CMP AX,TEMP_BUFF_LAST
JGE BUFF_EXCHANGE_RET
PUSH BX
PUSH DX
MOV BX,AX
MOV DX,[BX]
MOV BX,CX
MOV [BX],DX
POP DX
POP BX
INC CX
INC AX
JMP BUFF_EXCHNG_END
BUFF_EXCHANGE_RET:
;PUSH BX
;PUSH DX
;MOV DX,0DH
;MOV BX,CX
;MOV [BX],DX
;POP DX
;POP BX
;INC CX
;PUSH BX
;PUSH DX
;MOV DX,0AH
;MOV BX,CX
;MOV [BX],DX
;POP DX
;POP BX
MOV BUFF_LAST,CX
POP DX
POP CX
POP BX
POP AX
RET
;*********************************************************************
CR_LF:
MOV AL,13
CALL SEND_CHAR ;SEND A CARRIAGE RETURN
MOV AL,10
CALL SEND_CHAR ;SEND A LINE FEED
RET
;*********************************************************************
DISPLAY_CHAR:
PUSH BX ;SAVE THE ATTRIBUTE
CALL GET_CURS_ADDR ;GET ADDRESS OF BIOS CURSOR
MOV ES:[BX],DX ;TELL BIOS WHERE THE CURSOR IS
POP BX ;GET BACK THE ATTRIBUTE
MOV BH,ACTIVE_PAGE ;GET ACTIVE PAGE
PUSH CX ;SAVE THE LOOP COUNT
MOV CX,1 ;WRITE 1 CHARACTER
MOV AH,9 ;WRITE CHARACTER AND ATTRIBUTE
INT 10H
POP CX ;RECOVER LOOP COUNT
RET ;DONE WRITING THE CHARACTER
;*********************************************************************
READ_CHAR:
CALL GET_CURS_ADDR ;GET ADDRESS OF BIOS CURSOR
MOV ES:[BX],DX ;TELL BIOS WHERE THE CURSOR IS
MOV BH,ACTIVE_PAGE ;GET ACTIVE PAGE
MOV AH,8 ;BIOS FUNCTION TO READ CHARACTER
INT 10H ;READ THE CHARACTER/ATTRIBUTE
RET
;*********************************************************************
PRINT_CHAR:
PUSH DX
XOR AH,AH ;USE FUNCTION 0
XOR DX,DX ;PRINTER NUMBER 0
INT 17H ;BIOS PRINT CHARACTER FUNCTION
ROR AH,1 ;LOOK AT BIT ZERO
JNC PRINT_OK ;DID A TIMEOUT OCCUR?
MOV SEND_CHAR,OFFSET RETURN
PRINT_OK:
POP DX
RET ;DONE PRINTING CHARACTER
;*********************************************************************
BUFF_CHAR:
MOV BX,TEMP_BUFF_LAST ;GET LOCATION OF LAST CHARACTER
MOV [BX],AL ;PUT THE CHARACTER IN BUFFER
INC BX ;ADVANCE THE POINTER
MOV TEMP_BUFF_LAST,BX ;CHECK FOR BUFFER FULL
CMP BX,TEMP_BUFF_END ;IS THE BUFFER FULL YET?
JNE BUFF_OK ;IF NOT, KEEP GOING
MOV SEND_CHAR,OFFSET RETURN
BUFF_OK:
RET ;NOW ITS IN THE BUFFER
;*********************************************************************
FILE_BUFF_CHAR:
MOV BX,FILE_BUFF_LAST ;GET LOCATION OF LAST CHARACTER
MOV [BX],AL ;PUT THE CHARACTER IN BUFFER
INC BX ;ADVANCE THE POINTER
MOV FILE_BUFF_LAST,BX ;CHECK FOR BUFFER FULL
CMP BX,FILE_BUFF_END ;IS THE BUFFER FULL YET?
JNE FILE_BUFF_OK ;IF NOT, KEEP GOING
MOV FILE_SEND_CHAR,OFFSET RETURN
FILE_BUFF_OK:
RET ;NOW ITS IN THE BUFFER
;*********************************************************************
GET_CURS_ADDR:
MOV BL,ACTIVE_PAGE ;GET THE CURRENT PAGE NUMBER
XOR BH,BH ;CONVERT TO A WORD OFFSET
SHL BX,1 ;TIMES TWO FOR A WORD
ADD BX,OFFSET CURSOR_POSN ;ADD IN BASE ADDRESS
RET
;*********************************************************************
EXCHANGE_HELP:
XOR DX,DX ;START AT TOP LEFT CORNER
PUSH DI
LEA SI,HELP_MENU
MOV AH,15
INT 10H
CMP AL,7
JE MONO_HELP
LEA DI,HELP_MENU_ATTR1
JMP EXCHANGE_LOOP
MONO_HELP:
LEA DI,HELP_MENU_ATTR2
EXCHANGE_LOOP:
CMP DL,23 ;AT LAST COLUMN IN THIS ROW YET?
JL SWAP_CHAR
XOR DL,DL ;BACK TO FIRST COLUMN
INC DH ;DO THE NEXT ROW
CMP DH,4 ;AT LAST ROW YET?
JL SWAP_CHAR ;QUIT WHEN LAST ROW IS DONE
POP DI
RET
SWAP_CHAR:
CALL READ_CHAR ;READ CHARACTER AT THIS POSITION
XCHG AL,CS:[SI] ;SWAP WITH THE HELP TEXT
XCHG AH,CS:[DI] ;SWAP WITH THE HELP TEXT
MOV BL,AH ;ATTRIBUTE IS THE SAME
CALL DISPLAY_CHAR ;PUT NEW CHARACTER ON SCREEN
INC DL ;POINT TO NEXT POSITION
INC SI
INC DI
JMP EXCHANGE_LOOP
;*********************************************************************
TEST_FILENAME_CHAR:
CMP AL,2EH
JE FILECHAR_1
CMP AL,20H
JLE FILECHAR_1
CMP AL,22H
JE FILECHAR_1
CMP AL,25H
JE FILECHAR_1
CMP AL,2AH
JE FILECHAR_1
CMP AL,2BH
JE FILECHAR_1
CMP AL,2CH
JE FILECHAR_1
CMP AL,2FH
JE FILECHAR_1
CMP AL,3AH
JE FILECHAR_1
CMP AL,3BH
JE FILECHAR_1
CMP AL,3CH
JE FILECHAR_1
CMP AL,3DH
JE FILECHAR_1
CMP AL,3EH
JE FILECHAR_1
CMP AL,7FH
JGE FILECHAR_1
CMP AL,5BH
JE FILECHAR_1
CMP AL,5CH
JE FILECHAR_1
CMP AL,5DH
JE FILECHAR_1
CMP AL,5EH
JE FILECHAR_1
CMP AL,60H
JE FILECHAR_1
CMP FILE_EXT,00H
JE NOT_EXTEN
CMP CL,04H
JE FILECHAR_1
RET
NOT_EXTEN:
CMP CL,08H
JE FILECHAR_1
RET
FILECHAR_1:
MOV FILECHAR,01
RET
GET_FILENAME:
PUSH BX
PUSH AX
MOV AX,1BH
CALL FILE_SEND_CHAR
MOV AX,0046H
CALL FILE_SEND_CHAR
MOV AX,004CH
CALL FILE_SEND_CHAR
MOV AX,0020H
CALL FILE_SEND_CHAR
POP AX
PUSH DI
PUSH SI
MOV FILE_EXT,00H
MOV FILECHAR,00H
PUSH DX
PUSH CX
MOV CL,00H
MOV DX,TOP_LEFT
MOV DL,0
LEA SI,FILENAME
GET_FILENAME_1:
CALL READ_CHAR
CALL TEST_FILENAME_CHAR
CMP FILECHAR,00H
JNE END_OF_FILENAME_1
CMP FILE_EXT,00H
JNE FILE_EXTEN
MOV CS:[SI],AL
INC SI
FILE_EXTEN:
CALL FILE_SEND_CHAR
INC DL
INC CL
JMP GET_FILENAME_1
END_OF_FILENAME_1:
CMP CL,0
JE END_OF_FILENAME_A
CMP FILE_EXT,01H
JE AT_END_OF_FILENAME
MOV FILECHAR,00H
MOV FILE_EXT,01H
JMP FILE_EXTEN
AT_END_OF_FILENAME:
MOV AL,0AH
CALL FILE_SEND_CHAR
MOV AL,0DH
CALL FILE_SEND_CHAR
MOV AL,2EH
MOV CS:[SI],AL
INC SI
MOV AL,52H
MOV CS:[SI],AL
INC SI
MOV AL,54H
MOV CS:[SI],AL
INC SI
MOV AL,54H
MOV CS:[SI],AL
INC SI
FILL_TO_END:
CMP CL,0DH
JE END_OF_FILENAME_A
MOV AL,0H
MOV CS:[SI],AL
INC CL
INC SI
JMP FILL_TO_END
END_OF_FILENAME_A:
POP CX
POP DX
LEA SI,FILE_PROMPT ;POINT TO THE PROMPT FOR SOURCE
XOR DI,DI ;USE THE PSP FOR BUFFER
XOR DX,DX ;PUT PROMPT AT TOP LEFT CORNER
MOV CX,29 ;USE MAX OF 40 CHARACTERS
POP BX
DISPLAY_PROMPT:
PUSH CX ;SAVE LOOP COUNT
CALL READ_CHAR ;GET CHARACTER ON THIS LINE
MOV CS:[DI],AX ;STORE IT IN THE PSP
INC DI ;ADD TWO FOR NEXT CHARACTER
INC DI
MOV AL,CS:[SI] ;GET NEXT PROMPT CHARACTER
INC SI ;NEXT CHARACTER IN PROMPT
MOV BL,47H ;ATTRIBUTE FOR PROMPT
CALL DISPLAY_CHAR ;PUT UP THE PROMPT CHARACTER
INC DL ;POINT TO NEXT COLUMN
POP CX ;GET BACK LOOP COUNT
LOOP DISPLAY_PROMPT ;ENTIRE PROMPT AND FILENAME
FIND_LAST_LETTER:
DEC SI ;BACKUP TO LAST LETTER
DEC DL ;BACKUP TO LAST COLUMN
CMP BYTE PTR [SI],0 ;IS THIS A LETTER?
JE FIND_LAST_LETTER;BACKUP UNTILL A LETTER IS FOUND
INC DL ;PUT BLINKING BOX AT LAST LETTER
READ_KB:
MOV AL,219 ;ASCII FOR BOX CHARACTER
MOV BL,47H+80H ;MAKE IT A BLINKING BOX CHARACTER
CALL DISPLAY_CHAR ;WRITE THE BLINKING BOX
XOR AH,AH ;FUNCTIO 0 TO GET NEXT KEY
INT 16H ;BIOS KEYBOARD INPUT
CMP AL,13 ;IS IT A CARRIAGE RETURN?
JE ERASE_PROMPT
CMP AL,8 ;IS IT A BACKSPACE?
JE BACK_SPACE
CMP AH,1 ;IS IT ESCAPE?
JNE READ_KBDRD_2
MOV WRIT_FILE,-1 ;INDICATE ESCAPE IS REQUESTED
READ_KBDRD_1:
CMP DL,16 ;AT BEGINNING OF LINE?
JLE READ_KB ;IF YES, CAN'T BACKUP FROM HERE
MOV AL,0 ;WRITE A NORMAL BLANK (ASCII 0)
MOV BL,47H ;ATTRIBUTE FOR FILENAME
CALL DISPLAY_CHAR ;WRITE THE LETTER
DEC DL ;BACKUP THE CURSOR
JMP READ_KBDRD_1
READ_KBDRD_2:
CMP AL,"." ;IS IT A VALID LETTER?
JL READ_KB
CMP AL,"z" ;IS IT A VALID LETTER?
JG READ_KB
CMP DL,28 ;ONLY ALLOW 40 CHARACTERS
JGE READ_KB
TTY_KEY:
MOV WRIT_FILE,0 ;FIX ESCAPE HIT THEN CHARS.
MOV BL,47H ;ATTRIBUTE FOR FILENAME
CALL DISPLAY_CHAR ;WRITE THE LETTER
INC DL ;MOVE TO NEXT COLUMN
JMP READ_KB ;GET ANOTHER KEYSTROKE
BACK_SPACE:
CMP DL,16 ;AT BEGINNING OF LINE?
JLE READ_KB ;IF YES, CAN'T BACKUP FROM HERE
MOV AL,0 ;WRITE A NORMAL BLANK (ASCII 0)
MOV BL,47H ;ATTRIBUTE FOR FILENAME
CALL DISPLAY_CHAR ;WRITE THE LETTER
DEC DL ;BACKUP THE CURSOR
JMP READ_KB ;THEN GET THE NEXT KEY
ESC_RET:
MOV WRIT_FILE,-1 ;INDICATE ESCAPE IS REQUESTED
ERASE_PROMPT:
XOR AL,AL ;GET RID OF THE CURSOR
CALL DISPLAY_CHAR ;WRITE THE LETTER
LEA DI,FILE_PROMPT ;COPY TO FILENAME
XOR SI,SI ;COPY FROM PSP
XOR DX,DX ;PROMPT IS AT ROW ZERO
MOV CX,29 ;COPY ALL 40 CHARACTERS
ERASE_LOOP:
CALL READ_CHAR ;GET CHARACTER ON THIS LINE
MOV CS:[DI],AL ;PUT IN BACK IN MEMORY
INC DI
MOV AX,CS:[SI] ;GET THE ORIGINAL CHARACTER BACK
MOV BL,AH ;PUT ATTRIBUTE INTO BL
INC SI
INC SI
CALL DISPLAY_CHAR ;WRITE ORIGINAL CHARACTER
INC DL ;MOVE TO NEXT COLUMN
LOOP ERASE_LOOP ;ERASE THE ENTIRE PROMPT
POP SI
POP DI
RET
SNIPPER ENDP
;---------------------------------------------------------------------;
; THIS COPIES THE BUFFER CONTENTS TO A FILE. IT SHOULD ONLY BE CALLED ;
; WHEN DOS IS IN A STABLE AND REENTRANT CONDITION. ;
;---------------------------------------------------------------------;
WRITE_TO_FILE PROC NEAR
ASSUME DS:NOTHING, ES:NOTHING
MOV WRIT_FILE,0 ;TURN OFF REQUEST FLAG
PUSH AX ;MUST PRESERVE ALL REGISTERS
PUSH BX
PUSH CX
PUSH DX
PUSH DS
PUSH ES
PUSH CS
POP DS
ASSUME DS:CSEG ;DS POINTS TO OUR CODE SEGMENT
MOV AX,3524H ;GET DOS CRITICAL ERROR VECTOR
INT 21H ;DOS FUNCTION TO GET VECTOR
PUSH BX ;SAVE OLD VECTOR ON STACK
PUSH ES
; REPLACE THE DOS SEVERE ERROR INTERRUPT WITH OUR OWN ROUTINE.
MOV DX,OFFSET NEWINT24
MOV AX,2524H ;SETUP TO CHANGE INT 24h VECTOR
INT 21H ;CHANGE DOS SEVERE ERROR VECTOR
LEA SI,PATH_N_FILE
PATH_N_FILE_LOOP:
CMP BYTE PTR[SI],0
JE PNFL_DONE
MOV BYTE PTR[SI],0
INC SI
JMP PATH_N_FILE_LOOP
PNFL_DONE:
LEA DI,PATH_N_FILE
LEA SI,FILE_PATH
TRANSFER_PATH_N_FILE:
CMP BYTE PTR[SI],0
JE TPNF_DONE
PUSH BX
MOV BL,[SI]
MOV [DI],BL
POP BX
INC SI
INC DI
JMP TRANSFER_PATH_N_FILE
TPNF_DONE:
LEA SI,FILENAME
ADD_FILENAME_LOOP:
CMP BYTE PTR[SI],0
JE AFL_DONE
PUSH BX
MOV BL,[SI]
MOV [DI],BL
POP BX
INC SI
INC DI
JMP ADD_FILENAME_LOOP
AFL_DONE:
MOV DX,OFFSET PATH_N_FILE ;POINT TO FILENAME
; FIRST TRY TO OPEN THE FILE. IF DOS RETURNS WITH THE CARRY FLAG SET,
; THE FILE DIDN'T EXIST AND WE MUST CREATE IT. ONCE THE FILE IS OPENED,
; ADVANCE THE FILE POINTER TO THE END OF FILE TO APPEND.
MOV AX,3D02H ;DOS FUNCTION TO OPEN FILE
INT 21H ;DOS WILL RETURN WITH CARRY FLAG
JC FILE_NOT_FOUND ;SET IF FILE DOESN'T EXIST.
MOV BX,AX ;KEEP HANDLE IN BX ALSO
XOR CX,CX ;MOVE DOS FILE POINTER TO THE
XOR DX,DX ;END OF THE FILE. THIS LETS US
MOV AX,4202H ;APPEND THIS TO AN EXISTING FILE
INT 21H ;DOS FUNCTION TO MOVE POINTER
JNC WRITE_FILE ;IF NO ERROR, CONTINUE TO WRITE
DOS_ERROR:
CMP ERR_STAT,0 ;DID A SEVERE ERROR OCCUR?
JNE REP_VECTOR ;IF SEVERE ERROR, JUST QUIT
JMP SHORT CLOSE_FILE;JUST CLOSE THE FILE
FILE_NOT_FOUND: CMP ERR_STAT,0 ;DID A SEVERE ERROR OCCUR?
JNE REP_VECTOR ;IF SEVERE ERROR, JUST QUIT
MOV CX,0020H ;ATTRIBUTE FOR NEW FILE
MOV AH,3CH ;CREATE FILE FOR WRITING
INT 21H ;DOS FUNCTION TO CREATE FILE
JC DOS_ERROR ;ON ANY ERROR, TAKE JUMP
MOV BX,AX ;SAVE HANDLE IN BX
WRITE_FILE: MOV DX,BUFF_START ;POINT TO BUFFER
MOV CX,BUFF_LAST ;GET BUFFER POINTER
SUB CX,DX ;NUMBER OF CHARS IN BUFFER
MOV AH,40H ;DOS WRITE TO A DEVICE FUNCTION
INT 21H ;WRITE TO THE FILE
CLOSE_FILE:
MOV AH,3EH ;DOS FUNCTION TO CLOSE THE FILE
INT 21H
REP_VECTOR:
POP DS ;GET INT 24H VECTOR FROM STACK
POP DX
MOV AX,2524H ;RESTORE CRITICAL ERROR VECTOR
INT 21H ;DOS FUNCTION TO CHANGE VECTOR
POP ES ;FINALLY RESTORE ALL REGISTERS
POP DS
POP DX
POP CX
POP BX
POP AX
RET ;FINISHED WRITING TO DISK
WRITE_TO_FILE ENDP
;---------------------------------------------------------------------;
; INTERRUPT 09 ROUTINE. WATCH FOR TRIGGER KEY TO POP UP.
;---------------------------------------------------------------------;
NEWINT09 PROC FAR
ASSUME DS:NOTHING, ES:NOTHING
STI ;ALLOW OTHER INTERRUPTS
PUSH AX ;MUST SAVE PROCESSOR STATE
IN AL,60H ;GET THE SCAN CODE
CMP AL,HOTKEY ;IS IT THE HOT KEY?
JE TRIGGER ;IF YES, CHECK THE MASK
INT09_EXIT: POP AX ;RESTORE THE PROCESSOR STATE
JMP OLDINT09 ;CONTINUE WITH ROM ROUTINE
TRIGGER: MOV AH,2 ;GET KEYBOARD STATUS
INT 16H ;BIOS KEYBOARD SERVICE
AND AL,0FH ;Take lower four bits
CMP AL,SHIFT_MASK ;IS CTL KEY DOWN?
JNZ INT09_EXIT ;IF NOT, IGNORE IT
TEST BUSY_FLAGS,00000100B ;IS SNIPPER ALREADY ACTIVE?
JNZ INT09_EXIT ;IF ACTIVE, THEN EXIT
OR BUSY_FLAGS,00000100B ;ITS ACTIVE NOW
PUSHF
CALL OLDINT09 ;LET ROM PROCESS THE KEY
PUSH BX ;MUST PRESERVE ALL REGISTERS
PUSH CX
PUSH DX
PUSH BP
PUSH SI
PUSH DI
PUSH DS
PUSH ES
PUSH CS
POP DS ;SET DS TO CSEG
MOV AX,BIOS_SEG ;ES POINTS TO BIOS DATA AREA
MOV ES,AX
ASSUME DS:CSEG, ES:BIOS_SEG
CALL GET_CURS_ADDR ;CURSOR ADDRESS FOR THIS PAGE
PUSH ES:[BX] ;SAVE THE CURSOR LOCATION
CALL SNIPPER ;DO THE WINDOW
CALL GET_CURS_ADDR ;CURS0R ADDRESS FOR THIS PAGE
POP ES:[BX] ;GET BACK CURSOR POSITION
AND BUSY_FLAGS,11111011B ;SNIPPER IS NOT ACTIVE
POP ES ;RESTORE ALL REGISTERS
POP DS
POP DI
POP SI
POP BP
POP DX
POP CX
POP BX
POP AX
IRET ;NOW WERE ALL DONE
NEWINT09 ENDP
;---------------------------------------------------------------------;
; INTERRUPT 13 ROUTINE. SET BIOS BUST BIT ;
;---------------------------------------------------------------------;
NEWINT13 PROC FAR
ASSUME DS:NOTHING, ES:NOTHING
OR BUSY_FLAGS,00000010B ;SET BIOS BUSY BIT
PUSHF
CALL OLDINT13 ;DO THE BIOS FUNCTION
PUSHF ;SAVE RESULT FLAGS
AND BUSY_FLAGS,11111101B ;CLEAR BIOS BUSY BIT
POPF ;GET BACK RESULT FLAGS
STI ;MUST RETURN WITH INTERUPTS ON
RET 2 ;RETURN BIOS RESULT FLAGS
NEWINT13 ENDP
;---------------------------------------------------------------------;
; INTERRUPT 16 ROUTINE. INSERT KEYSTROKES FROM BUFFER ;
;---------------------------------------------------------------------;
NEWINT16 PROC FAR
ASSUME DS:NOTHING, ES:NOTHING
PUSH BX
CMP SEND_KEYS,1 ;SENDING KEYS FROM BUFFER?
JE INSERT_KEY ;IF YES, THEN GET NEXT ONE
CMP FILE_SEND_KEYS,1 ;SENDING KEYS FROM BUFFER?
JE FILE_INSERT_KEY ;IF YES, THEN GET NEXT ONE
CMP WRIT_FILE,1 ;ANYTHING TO WRITE TO DISK?
JE CHECK_DOS_STAT ;IF YES, THIS IS THE TIME
BIOS_KB:
POP BX
JMP OLDINT16 ;JUST DO NORMAL KB ROUTINE
CHECK_DOS_STAT:
CMP DOS_STAT,0AH ;DOING READ STRING?
JE BEGIN_NOW ;IF YES, ITS SAFE TO BEGIN
CMP DOS_STAT,8 ;DOING KEYBOARD INPUT?
JNE BIOS_KB ;IF YES, ITS SAFE TO BEGIN
BEGIN_NOW:
STI ;GET INTERRUPTS BACK ON
CALL WRITE_TO_FILE ;EMPTY THE BUFFER
JMP BIOS_KB ;CONTINUE WITH BIOS ROUTINE
INSERT_KEY:
STI ;INTERRUPTS BACK ON
MOV BX,BUFF_NEXT ;GET ADDRESS OF NEXT BYTE
CMP BX,BUFF_LAST ;AT END OF BUFFER YET?
JL GET_A_KEY ;IF NOT, GET THE NEXT ONE
MOV SEND_KEYS,0 ;WHEN DONE, TURN OFF SEND SWITCH
GET_A_KEY:
MOV AL,CS:[BX] ;GET THE NEXT KEY CODE
CMP AL,10 ;IS IT A LINE FEED?
JNE NOT_LF ;DONT RETURN THE LINE FEEDS
INC BUFF_NEXT ;SKIP TO NEXT KEY
JMP INSERT_KEY
NOT_LF:
CMP AH,1 ;REQUEST FOR STATUS ONLY?
JE RETURN_STATUS ;IF YES, RETURN STATUS ONLY
CMP AH,0 ;REQUEST TO GET THE NEXT KEY
JNE BIOS_KB ;IF NOT, IGNORE THIS FUNCTION
INC BX ;REMOVE THIS KEY FROM OUR BUFFER
MOV BUFF_NEXT,BX ;SAVE THE POINTER TO NEXT KEY
RETURN_STATUS:
OR BL,1 ;CLEAR ZERO FLAG TO INDICATE A
POP BX ;KEY IS AVAILIABLE
RET 2 ;RETURN WITH THESE FLAGS
FILE_INSERT_KEY:
STI ;INTERRUPTS BACK ON
MOV BX,FILE_BUFF_NEXT ;GET ADDRESS OF NEXT BYTE
CMP BX,FILE_BUFF_LAST ;AT END OF BUFFER YET?
JL FILE_GET_A_KEY ;IF NOT, GET THE NEXT ONE
MOV FILE_SEND_KEYS,0 ;WHEN DONE, TURN OFF SEND SWITCH
FILE_GET_A_KEY:
MOV AL,CS:[BX] ;GET THE NEXT KEY CODE
CMP AL,10 ;IS IT A LINE FEED?
JNE FILE_NOT_LF ;DONT RETURN THE LINE FEEDS
INC FILE_BUFF_NEXT ;SKIP TO NEXT KEY
JMP FILE_INSERT_KEY
FILE_NOT_LF:
CMP AH,1 ;REQUEST FOR STATUS ONLY?
JE FILE_RETURN_STATUS ;IF YES, RETURN STATUS ONLY
CMP AH,0 ;REQUEST TO GET THE NEXT KEY
JNE BIOS_KB ;IF NOT, IGNORE THIS FUNCTION
INC BX ;REMOVE THIS KEY FROM OUR BUFFER
MOV FILE_BUFF_NEXT,BX ;SAVE THE POINTER TO NEXT KEY
FILE_RETURN_STATUS:
OR BL,1 ;CLEAR ZERO FLAG TO INDICATE A
POP BX ;KEY IS AVAILIABLE
RET 2 ;RETURN WITH THESE FLAGS
NEWINT16 ENDP
;---------------------------------------------------------------------;
; INTERRUPT 21 ROUTINE. THIS ROUTINE IS USED TO MONITOR DOS FUNCTION ;
; CALLS. IF THE BUFFER NEEDS TO BE FLUSHED, IT WIL BE DONE HERE. ;
;---------------------------------------------------------------------;
NEWINT21 PROC FAR
ASSUME DS:NOTHING, ES:NOTHING
STI
OR AH,AH ;DOING FUNCTION ZERO?
JNE NOT_ZERO
MOV AH,4CH ;IF YES, CHANGE IT TO A 4CH
NOT_ZERO:
OR BUSY_FLAGS,00000001B ;SET DOS BUSY BIT
MOV DOS_STAT,AH
PUSHF ;SIMULATE AN INTERRUPT
CALL OLDINT21 ;DO THE DOS FUNCTION
PUSHF ;SAVE THE RESULT FLAGS
AND BUSY_FLAGS,11111110B ;CLEAR DOS BUSY BIT
CMP WRIT_FILE,1 ;ANYTHING TO WRITE TO DISK?
JNE NO_WRITE ;IF NOT JUST RETURN
CALL WRITE_TO_FILE ;SAFE TO ACCESS DISK NOW
NO_WRITE:
POPF ;RECOVER DOS RESULT FLAGS
RET 2 ;RETURN WITH DOS RESULT FLAGS
NEWINT21 ENDP
;---------------------------------------------------------------------;
; NEW INTERRUPT 24H (CRITICAL DOS ERROR). THIS INTERRUPT IS ONLY IN ;
; EFFECT ONLY DURING A WRITE SCREEN. IT IS REQUIRED TO SUPPRESS THE ;
; 'ABORT, RETRY, IGNORE' MESSAGE. ALL FATAL DISK ERRORS ARE IGNORED. ;
;---------------------------------------------------------------------;
NEWINT24 PROC FAR
ASSUME CS:CSEG, DS:NOTHING, ES:NOTHING
STI ;TURN INTERRUPTS BACK ON
INC ERR_STAT ;SET THE ERROR FLAG
XOR AL,AL ;TELLS DOS TO IGNORE THE ERROR
IRET ;THATS ALL WE DO HERE
NEWINT24 ENDP
;--------------------------------------------------------------------;
; HERE IS THE CODE USED TO INITIALIZE SNIPPER. ;
;--------------------------------------------------------------------;
ASSUME CS:CSEG, DS:CSEG, ES:CSEG
INITIALIZE:
LEA DX,COPYRIGHT
MOV AH,9 ;DOS DISPLAY STRING SERVICE
INT 21H ;DISPLAY TITLE MESSAGE
; SEARCH FOR AN PREVIOUSLY INSTALLED COPY OF SNIPPER
NOT BYTE PTR START ;MODIFY TO AVOID FASLE MATCH
XOR BX,BX ;START SEARCH AT SEGMENT ZERO
MOV AX,CS ;COMPARE TO THIS CODE SEGMENT
NEXT_SEGMENT:
INC BX ;LOOK AT NEXT SEGMENT
CMP AX,BX ;UNTIL REACHING THIS CODE SEG
MOV ES,BX
JE NOT_INSTALLED
LEA SI,START ;SETUP TO COMPARE STRINGS
MOV DI,SI
MOV CX,16 ;16 BYTES MUST MATCH
REP CMPSB ;COMPARE DS:SI TO ES:DI
OR CX,CX ;DID THE STRINGS MATCH?
JNE NEXT_SEGMENT ;IF NO MATCH, TRY NEXT SEGMENT
LEA DX,INSTALLED_MSG
JMP SHORT ERR_EXIT
NOT_INSTALLED:
MOV AH,30H
INT 21H ;GET DOS VERSION NUMBER
CMP AL,2 ;IS IT HIGHER THAN 2.0?
JNB VER_OK ;IF YES, PROCEED
LEA DX,BAD_DOS_MSG
ERR_EXIT:
MOV AH,9 ;DOS DISPLAY STRING SERVICE
INT 21H ;DISPLAY ERRER MESSAGE
RET ;RETURN TO DOS
EXIT_NON_TSR:
MOV AH,4CH
INT 21H
VER_OK:
INC SI ;POINT TO FIRST PARAMETER
MOV SI,81H ;POINT TO PARAMETER AREA
CALL GET_PARAM ;GET FIRST PARAMETER (ROWS)
PUSH AX ;SAVE THE ROW COUNT
CALL GET_PARAM ;GET SECOND PARAMETER (COLUMNS)
ADD AX,2 ;ADD SPACE FOR CR AND LF
POP BX ;GET BACK FIRST PARAMETER
MUL BX ;PRODUCT OF ROWS AND COLUMNS
OR AX,AX ;WAS ANYTHING ENTERED?
JE NO_PARAMS ;IF NOT, USE DEFAULT VALUE
CMP AX,10000 ;MAXIMUM BUFFER IS 10000 BYTES
JLE SIZE_IS_OK
MOV AX,10000
SIZE_IS_OK:
ADD AX,BUFF_START
MOV BUFF_END,AX ;SET THE NEW BUFFER SIZE
NO_PARAMS:
MOV AX,BIOS_SEG ;LOOK AT BIOS DATA AREA
MOV ES,AX
ASSUME ES:BIOS_SEG
CMP ROWS,0 ;IS NUMBER OF ROWS ENTERED HERE
JNE MUST_BE_EGA ;IF YES, AN EGA MAY BE PRESENT
MOV ROWS,24 ;IF NOT EGA, MUST BE 24 ROWS
MUST_BE_EGA:
ASSUME ES:NOTHING
MOV AX,3509H ;GET KEYBOARD BREAK VECTOR
INT 21H
MOV WORD PTR [OLDINT09], BX ;SAVE SEGMENT
MOV WORD PTR [OLDINT09+2],ES ;SAVE OFFSET
MOV DX, OFFSET NEWINT09
MOV AX, 2509H
INT 21H ;DOS FUNCTION TO CHANGE VECTOR
MOV AX,3513H ;GET BIOS DISK INTERRUPT VECTOR
INT 21H
MOV WORD PTR [OLDINT13], BX ;SAVE SEGMENT
MOV WORD PTR [OLDINT13+2],ES ;SAVE OFFSET
MOV DX, OFFSET NEWINT13
MOV AX, 2513H
INT 21H ;DOS FUNCTION TO CHANGE VECTOR
MOV AX,3516H ;GET KEYBOARD INPUT VECTOR
INT 21H
MOV WORD PTR [OLDINT16], BX ;SAVE SEGMENT
MOV WORD PTR [OLDINT16+2],ES ;SAVE OFFSET
MOV DX, OFFSET NEWINT16
MOV AX, 2516H
INT 21H ;DOS FUNCTION TO CHANGE VECTOR
MOV AX,3521H ;GET DOS FUNCTION VECTOR
INT 21H
MOV WORD PTR [OLDINT21], BX
MOV WORD PTR [OLDINT21+2],ES
MOV DX, OFFSET NEWINT21
MOV AX, 2521H
INT 21H ;DOS FUNCTION TO CHANGE VECTOR
CALL GET_PARAM
;--------------------------------------------------------------------;
; DEALLOCATE OUR COPY OF THE ENVIORNMENT. ;
; EXIT USING INT 27H. LEAVE CODE AND SPACE FOR BUFFER RESIDENT. ;
;--------------------------------------------------------------------;
MOV AX,DS:[002CH] ;GET SEGMENT OF ENVIORNMENT
MOV ES,AX ;PUT IT INTO ES
MOV AH,49H ;RELEASE ALLOCATED MEMORY
INT 21H
MOV DX,FILE_BUFF_END;LEAVE THIS MUCH RESIDENT
INT 27H ;TEMINATE AND STAY RESIDENT
;---------------------------------------------------------;
; GET_PARAM RETRIEVES AN INTEGER FROM THE COMMAND LINE. ;
;---------------------------------------------------------;
GET_PARAM:
XOR AX,AX ;CLEAR AX FOR TOTAL
GET_DIGIT:
MOV BL,[SI] ;GET CHARACTER INTO BL
CMP BL,0DH ;IS IT THE LAST ONE?
JE DONE
INC SI ;POINT TO NEXT CHARACTER
CMP BL,"," ;IS IT THE DELIMITER?
JE DONE
CMP BL,"/" ;IS IT THE DELIMITER?
JE GET_THE_PATH
SUB BL,30H ;CONVERT ASCII TO INTEGER
JB GET_DIGIT ;IS IT A VALID DIGIT
CMP BL,9
JA GET_DIGIT ;IF NOT VALID, JUST SKIP IT
MOV BH,10 ;TIMES 10 FOR NEXT DIGIT
MUL BH ;MULTIPLY SUM AND ADD THIS DIGIT
ADD AL,BL ;ADD DIGIT TO SUM
JMP GET_DIGIT ;READ ALL CHARACTERS ON LINE
GET_THE_PATH:
MOV BL,[SI]
CMP BL,50H
JE PATH_FLAG_OK
CMP BL,70H
JNE DONE
PATH_FLAG_OK:
INC SI
MOV BL,[SI]
CMP BL,3DH
JNE DONE
INC SI
LEA DI,FILE_PATH
GET_THE_PATH_LOOP:
MOV BL,[SI]
CMP BL,0DH
JE PATH_DONE
MOV [DI],BL
INC SI
INC DI
JMP GET_THE_PATH_LOOP
PATH_DONE:
MOV BYTE PTR[DI],5CH
DONE:
RET
CSEG ENDS
END START